package ca.ericslandry.client.mvp.view;

import java.util.List;
import java.util.Set;

import ca.ericslandry.client.MapsUtils;
import ca.ericslandry.client.mvp.presenter.IssuePresenter;
import ca.ericslandry.client.mvp.presenter.PlacesPresenter;
import ca.ericslandry.shared.domain.Issue;
import ca.ericslandry.shared.util.GeoHash;

import com.allen_sauer.gwt.log.client.Log;
import com.google.code.gwt.geolocation.client.Coordinates;
import com.google.code.gwt.geolocation.client.Geolocation;
import com.google.code.gwt.geolocation.client.Position;
import com.google.code.gwt.geolocation.client.PositionCallback;
import com.google.code.gwt.geolocation.client.PositionError;
import com.google.code.gwt.geolocation.client.PositionOptions;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.control.LargeMapControl;
import com.google.gwt.maps.client.event.MarkerClickHandler;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.overlay.Icon;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.maps.client.overlay.PolyStyleOptions;
import com.google.gwt.maps.client.overlay.Polygon;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Widget;

public class PlacesView extends BaseView implements PlacesPresenter.Display, ResizeHandler {
	private MapWidget map;
	private LatLng centerPoint;
	private HorizontalPanel panel = new HorizontalPanel();

	public PlacesView() {
		panel.setSize("99%", "99%");
		panel.setSpacing(5);
		map = new MapWidget();
		map.setPixelSize(600, 500);
		map.setZoomLevel(13);
		map.addControl(new LargeMapControl());
		panel.add(map);
		Window.addResizeHandler(this);
	}

	public Widget asWidget() {
		return panel;
	}

	@Override
	public void onResize(ResizeEvent event) {
		onWindowResized(event.getWidth(), event.getHeight());
	}

	public void onWindowResized(int width, int height) {
		int mapX = map.getAbsoluteLeft();
		int mapY = map.getAbsoluteTop();
		int newWidth = width - mapX - 9;
		int newHeight = height - mapY - 9;
		map.setPixelSize(newWidth, newHeight);
	}

	public void center() {
		if (Geolocation.isSupported()) {
			Geolocation geo = Geolocation.getGeolocation();
			if (geo == null) {
				Log.warn("Geolocation is supported in this browser, but it didn't work.");
			} else {
				geo.getCurrentPosition(new PositionCallback() {
					@Override
					public void onSuccess(Position position) {
						Coordinates c = position.getCoords();
						LatLng point = LatLng.newInstance(c.getLatitude(), c.getLongitude());
						Log.info("Browser geolocated here:" + point);
						map.setCenter(point);
					}

					@Override
					public void onFailure(PositionError error) {
						String message = "";
						switch (error.getCode()) {
						case PositionError.UNKNOWN_ERROR:
							message = "Unknown Error";
							break;
						case PositionError.PERMISSION_DENIED:
							message = "Permission Denied";
							break;
						case PositionError.POSITION_UNAVAILABLE:
							message = "Position Unavailable";
							break;
						case PositionError.TIMEOUT:
							message = "Time-out";
							break;
						default:
							message = "Unknown error code.";
						}
						Log.warn("Failed to acquire geolocation from browser because of: " + message);
					}
				}, PositionOptions.getPositionOptions(false, 15000, 30000));
			}
		}
	}

	@Override
	public void startProcessing() {
		super.startProcessing();
		onWindowResized(Window.getClientWidth(), Window.getClientHeight());
		map.clearOverlays();
	}

	public void addMarkers(List<Issue> issueList) {
		int i = 0;
		for (Issue dto : issueList) {
			String geohash = dto.getGeohash();
			if (geohash != null && !geohash.isEmpty()) {
				LatLng point = GeoHash.fromGeohashString(geohash).getPoint().toLatLng();
				Icon icon = MapsUtils.createLetteredIcon(MapsUtils.LETTERS[i]);
				MarkerOptions options = MarkerOptions.newInstance(icon);
				Marker marker = new Marker(point, options);
				marker.addMarkerClickHandler(new IssueMarkerClickHandler(dto));
				map.addOverlay(marker);
			}
			i++;
		}

		Icon icon = MapsUtils.createPushpinIcon();
		MarkerOptions options = MarkerOptions.newInstance(icon);
		map.getInfoWindow().open(centerPoint, new InfoWindowContent("You are here"));
		map.addOverlay(new Marker(centerPoint, options));

		GeoHash fromLatLng = GeoHash.fromLatLng(centerPoint);
		String geohash = fromLatLng.toBase32();
		String substring = geohash.substring(0, 5);
		Polygon boundingBox = GeoHash.fromGeohashString(substring).getBoundingBox();
		PolyStyleOptions style = PolyStyleOptions.newInstance("#f33f00", 3, 0.3);
		boundingBox.setFillStyle(style);
		map.addOverlay(boundingBox);
		Log.info("Got here");

	}

	private class IssueMarkerClickHandler implements MarkerClickHandler {
		private Issue dto;

		public IssueMarkerClickHandler(Issue dto) {
			this.dto = dto;
		}

		@Override
		public void onClick(MarkerClickEvent event) {
			String geohash = dto.getGeohash();
			LatLng point = GeoHash.fromGeohashString(geohash).getPoint().toLatLng();
			Hyperlink link = IssuePresenter.getLinkViewIssue(dto);
			map.getInfoWindow().open(point, new InfoWindowContent(link));
		}
	}

	@Override
	public Set<String> getPreferredGeohash() {
		return null;
	}

	@Override
	public void reset() {
	}

	@Override
	public void showGrid() {
	}

	@Override
	public void showIssue(Long id) {
	}

	@Override
	public void showIssues(List<Issue> issues) {
	}

	// @Override
	// public void createLegend(List<Issue> issueList) {
	// panel.clear();
	// int i = 0;
	// for (Issue dto : issueList) {
	// String id = String.valueOf(dto.getId());
	// PlaceRequest placeRequest = new
	// PlaceRequest(PlacesPresenter.PLACE).with(IssuePresenter.PARAM_ID, id);
	// Hyperlink link = new Hyperlink(dto.getTitle(), placeRequest.toString());
	//
	// HorizontalPanel row = new HorizontalPanel();
	// row.setSpacing(5);
	// row.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
	// row.add(new HTML("<img src=\"http://www.google.com/mapfiles/marker" +
	// MapsUtils.LETTERS[i++] + ".png\"/>"));
	// row.add(link);
	// panel.add(row);
	// }
	// }

}